//
//  MMPaintingView.m
//  MemeMaker
//
//  Created by Phan Quang Ha on 7/9/13.
//  Copyright (c) 2013 soyo. All rights reserved.
//

#import "MMPaintingView.h"
#import "MMBasicPen.h"
#import "MMMovableImage.h"
#import "MMMovableText.h"

#import "MMCircleView.h"

CGPoint midPoint(CGPoint p1, CGPoint p2)
{
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}

@interface MMPaintingView ()
{
    CGPoint previousPoint;
    CGPoint fromPoint;
    CGPoint endPoint;
    
    BOOL mouseSwiped;
    
    MMCircleView *eraserView;
}

@end

@implementation MMPaintingView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        _imgTempPainting = [[UIImageView alloc] initWithFrame:self.bounds];
        _imgMainPainting = [[UIImageView alloc] initWithFrame:self.bounds];
        
        [self addSubview:_imgTempPainting];
        [self addSubview:_imgMainPainting];
        
        _currentPen = [[MMBasicPen alloc] init];
        
        [self bringSubviewToFront:_imgTempPainting];
        
        eraserView = [[MMCircleView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
        eraserView.hidden = YES;
        [self addSubview:eraserView];
        
        self.bgColor = [UIColor whiteColor];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedMovingSubViewWithNotification:) name:NOTIFY_UPDATE_PREVIEWING_PICTURE object:nil];
    }
    return self;
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        _imgTempPainting = [[UIImageView alloc] initWithFrame:self.bounds];
        _imgMainPainting = [[UIImageView alloc] initWithFrame:self.bounds];
        
        [self addSubview:_imgTempPainting];
        [self addSubview:_imgMainPainting];
        
        _currentPen = [[MMBasicPen alloc] init];
        
        [self bringSubviewToFront:_imgTempPainting];
        
        eraserView = [[MMCircleView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
        eraserView.hidden = YES;
        [self addSubview:eraserView];
        
        self.bgColor = [UIColor whiteColor];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedMovingSubViewWithNotification:) name:NOTIFY_UPDATE_PREVIEWING_PICTURE object:nil];
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

- (void)drawLine
{
    //UIGraphicsBeginImageContext(self.bounds.size);
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    
    //draw old image
    
    
    //calculate mid point
    CGPoint mid1 = midPoint(previousPoint, fromPoint);
    CGPoint mid2 = midPoint(fromPoint, endPoint);
    
    //draw path
    CGContextMoveToPoint(currentContext, mid1.x, mid1.y);
    CGContextAddQuadCurveToPoint(currentContext, fromPoint.x, fromPoint.y, mid2.x, mid2.y);
    
    //set path properties
    if (_isErasing) {
        [self.imgMainPainting.image drawInRect:self.bounds];
        CGContextSetLineCap(currentContext, kCGLineCapRound);
        CGContextSetLineWidth(currentContext, _eraserSize);
        CGContextSetStrokeColorWithColor(currentContext, [UIColor clearColor].CGColor);
        CGContextSetBlendMode(currentContext, kCGBlendModeClear);
        CGContextStrokePath(currentContext);
        self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    }else{
        [self.imgTempPainting.image drawInRect:self.bounds];
        CGContextSetLineCap(currentContext, kCGLineCapRound);
        CGContextSetLineWidth(currentContext, _currentPen.pSize);
        CGContextSetRGBStrokeColor(currentContext, _currentPen.pRed, _currentPen.pGreen, _currentPen.pBlue, 1.0);
        CGContextSetBlendMode(currentContext, kCGBlendModeNormal);
        CGContextStrokePath(currentContext);
        self.imgTempPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    }
    
    
    //stroke path and assign to temp imageview
    
    
    CGContextFlush(currentContext);
    UIGraphicsEndImageContext();
    
    
}
- (void) drawPoint
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    
    
    CGContextMoveToPoint(currentContext, fromPoint.x, fromPoint.y);
    CGContextAddLineToPoint(currentContext, fromPoint.x, fromPoint.y);
    
    if (_isErasing) {
        [self.imgMainPainting.image drawInRect:self.bounds];
        CGContextSetLineCap(currentContext, kCGLineCapRound);
        CGContextSetLineWidth(currentContext, _eraserSize);
        CGContextSetStrokeColorWithColor(currentContext, [UIColor clearColor].CGColor);
        CGContextSetBlendMode(currentContext, kCGBlendModeClear);
        CGContextStrokePath(currentContext);
        self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    }else{
        [self.imgTempPainting.image drawInRect:self.bounds];
        CGContextSetLineCap(currentContext, kCGLineCapRound);
        CGContextSetLineWidth(currentContext, _currentPen.pSize);
        CGContextSetRGBStrokeColor(currentContext, _currentPen.pRed, _currentPen.pGreen, _currentPen.pBlue, 1.0);
        CGContextSetBlendMode(currentContext, kCGBlendModeNormal);
        CGContextStrokePath(currentContext);
        self.imgTempPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    }
    
    

    CGContextFlush(currentContext);
    UIGraphicsEndImageContext();
}
- (void) drawPreview
{
    [self clear];
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    [self.imgTempPainting.image drawInRect:self.bounds];
    
    CGContextMoveToPoint(currentContext, 27, 50);
    CGContextAddCurveToPoint(currentContext, 100, -20, 170, 100, 269, 50);
    
    CGContextSetLineCap(currentContext, kCGLineCapRound);
    CGContextSetRGBStrokeColor(currentContext, _currentPen.pRed, _currentPen.pGreen, _currentPen.pBlue, 1.0);
    CGContextSetLineWidth(currentContext, _currentPen.pSize);
    CGContextSetBlendMode(currentContext, kCGBlendModeNormal);
    
    CGContextStrokePath(currentContext);
    self.imgTempPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    self.imgTempPainting.alpha = _currentPen.pOpacity;
    
    CGContextFlush(currentContext);
    UIGraphicsEndImageContext();
}
- (void) clear
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    
    self.imgTempPainting.image = self.imgMainPainting.image = nil;
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor clearColor].CGColor);
    CGContextFillRect(UIGraphicsGetCurrentContext(), self.bounds);
    self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:NO];
    }
}
#pragma mark - Draw Image+text
- (void)drawImage:(UIImage *)img atRect:(CGRect)rect blendMode:(CGBlendMode)blendMode andAlpha:(CGFloat)alpha
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [self.imgMainPainting.image drawInRect:self.bounds];
    [img drawInRect:rect blendMode:blendMode alpha:alpha];
    self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:NO];
    }
}
- (void)drawText:(NSString *)text atRect:(CGRect)rect withFont:(UIFont *)font color:(UIColor *)color andTextAlignment:(NSTextAlignment)alignment
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [self.imgMainPainting.image drawInRect:self.bounds];
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), color.CGColor);
    [text drawInRect:rect withFont:font lineBreakMode:NSLineBreakByWordWrapping alignment:alignment];
    self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:NO];
    }   
}

#pragma mark - Touch Events
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_dState == sDrawing) {
        mouseSwiped = NO;
        UITouch *touch = [touches anyObject];
        
        previousPoint = [touch previousLocationInView:self];
        fromPoint = [touch locationInView:self];
        
        eraserView.center = fromPoint;
    }
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_dState == sDrawing) {
        mouseSwiped = YES;
        
        UITouch *touch = [touches anyObject];
        previousPoint = fromPoint;
        fromPoint = [touch previousLocationInView:self];
        endPoint = [touch locationInView:self];
        
        [self drawLine];
        [self.imgTempPainting setAlpha:_currentPen.pOpacity];
        
        if (_isErasing) {
            eraserView.center = endPoint;
            eraserView.hidden = NO;
        }
    }
    
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_dState == sDrawing) {
        if (!mouseSwiped) {
            [self drawPoint];
        }
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
        [self.imgMainPainting.image drawInRect:self.bounds];
        [self.imgTempPainting.image drawInRect:self.bounds blendMode:kCGBlendModeNormal alpha:_currentPen.pOpacity];
        self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
        self.imgTempPainting.image = nil;
        UIGraphicsEndImageContext();
        
        if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
            [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:NO];
        }
        
        eraserView.hidden = YES;
    }
    
}

#pragma mark - Custom Methods
- (void) increaseHeight:(CGFloat)height
{
    CGRect oldBounds = self.bounds;
    
    CGRect oldFrame = self.frame;
    oldFrame.size.height = oldFrame.size.height + height;
    self.frame = oldFrame;
    CGRect newBounds = self.bounds;
    
    _imgMainPainting.frame = newBounds;
    _imgTempPainting.frame = newBounds;
    
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    
    [self.imgMainPainting.image drawInRect:oldBounds];
    self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:YES];
    }
}
- (void) beginEditImage:(UIImage *)img
{
    CGSize paintingSize = self.frame.size;
    CGFloat targetHeight = img.size.height/img.size.width * paintingSize.width;
    CGFloat diffHeight = targetHeight -  paintingSize.height;
    
    CGRect oldFrame = self.frame;
    oldFrame.size.height = oldFrame.size.height + diffHeight;
    self.frame = oldFrame;
    CGRect newBounds = self.bounds;
    
    _imgMainPainting.frame = newBounds;
    _imgTempPainting.frame = newBounds;
    
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [img drawInRect:self.bounds];
    self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:YES];
    }
}

- (void)receivedMovingSubViewWithNotification:(NSNotification *)noti
{
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:YES];
    }
}

- (UIImage *)getFullImage
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor whiteColor].CGColor);
    CGContextFillRect(UIGraphicsGetCurrentContext(), self.bounds);
    
    [self.imgMainPainting.image drawInRect:self.bounds];
    switch (_dState) {
        case sAddingText:
        {
            CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), _movingText.mTextColor.CGColor);
            [_movingText.mString drawInRect:_movingText.frame withFont:_movingText.mFont lineBreakMode:NSLineBreakByWordWrapping alignment:_movingText.mTextAlignment];
        }
            break;
        case sAddingImage:
        {
            [_movingImage.mImage drawInRect:_movingImage.frame blendMode:kCGBlendModeNormal alpha:1.0f];
        }
            break;
        default:
            break;
    }
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}
- (void)setEraserSize:(CGFloat)eraserSize
{
    _eraserSize = eraserSize;
    eraserView.frame = CGRectMake(0, 0, eraserSize, eraserSize);
}

- (void)drawLogImage:(UIImage *)img
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [img drawInRect:CGRectMake(0, 0, self.bounds.size.width, img.size.width/self.bounds.size.width*img.size.height)];
    self.imgMainPainting.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    if (_delegate && [_delegate respondsToSelector:@selector(didChangeWithImage:rect:isNotification:)]) {
        [_delegate didChangeWithImage:[self getFullImage] rect:self.bounds isNotification:YES];
    }
}


//dealloc
- (void) dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
